#!/usr/bin/python2.4
#
# Copyright 2008 Google Inc.
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#      http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Root page."""

import logging
import os
import re
from google.appengine.api import urlfetch
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import login_required
import instantvidsite
import browse
import wsgiref.handlers


#TODO(gabe): implement clear my authsub token
#TODO(gabe): display favorite video

logging.getLogger().setLevel(logging.DEBUG)


class Account(webapp.RequestHandler):
  
  """Account page."""
  
  def GetUserUnknownVideos(self, site, user, session_token, user_videos,
                           updated_videos):
    
    """retrieve video status for users with unknown status."""
          
    videos = instantvidsite.Video.gql("WHERE user = :1 AND status = :2 AND site = :3", user,
                                 'unknown', site.key())
    
    for current in videos:
      modified = False
      video_id = current.id
      uservid = {'id': video_id, 'state': 'unknown', 'reason': 'unknown',
                 'isLive': False}
      user_videos.append(uservid)
                      
      fetch_result = urlfetch.Fetch('http://gdata.youtube.com/feeds/api/users/default/uploads/'
                                    + video_id, method=urlfetch.GET, 
        headers={'Authorization': browse.BuildAuthHeader(session_token)})
  
      # not real or immediately after upload
      if str(fetch_result.status_code) != "200":
        continue
  
#      logging.debug("retrieve id "+str(video_id))
#      logging.debug(str(fetch_result.status_code))
#      logging.debug(fetch_result.content)
            
      # if can't find app draft, this is live
      m = re.search('<app:draft.*', fetch_result.content)
      if m is None:
        modified = True
        uservid['isLive'] = True
        uservid['state'] = 'live'
                        
      else:
      # find state
        modified = False
              
        m = re.search('<yt:state name=\'([^\']*)\'', fetch_result.content)
        if m is not None:
          video_state = m.group(1)
          modified = True
          uservid['state'] = browse.if_else(video_state == 'rejected',
                                              'rejected', 'unknown')
        
        #find reason_code
        m = re.search('reasonCode=\'([^\']*)\'', fetch_result.content)
        if m is not None:
          reason_code = m.group(1)
          modified = True
          uservid['reason'] = reason_code
              
      #update video entry if modified
      if modified:
        current.status = uservid['state']
        current.reason = uservid['reason']
        updated_videos.append(current)

  @login_required
  def get(self, sitepath):
        
    """display status of all videos uploaded on the site."""
    
    #TODO(gabe): add confirm to remove video link
    user = users.GetCurrentUser()
    user_videos = []
    updated_videos = []
    
    #find domain
    site = instantvidsite.GetSite(sitepath)
    if not site:
      logging.error('bad sitepath - '+str(sitepath))      
      self.redirect("/?error=siteunknown")
      return
                
    #logging.debug(user.auth_domain())
    t_user = browse.GetTubeUser(site)
    #create account if none when accessing account page
    if t_user is None:
      t_user = instantvidsite.TubeUser()
      t_user.user = user
      t_user.site = site.key()
      t_user.put()
                           
    session_token = t_user.auth_token
    
    if session_token is not None:
      # get updates for videos with unknown status or in processing status
      self.GetUserUnknownVideos(site, user, session_token, user_videos,
                                updated_videos)
      #logging.debug('unknown vids processed - '+str(len(user_videos)) + ' & ' +
       #             str(len(updated_videos))+ ' modified')
      #logging.debug(user_videos)      
    else:
      pass  #try with unauthenticated feed instead
    
    # grab all known videos from this user   
    vids = instantvidsite.Video.gql("WHERE user = :1 AND status = :2 AND site = :3",
                               user, 'live', site.key())
    user_videos.extend(browse.ConvertVideosToDisplayObjects(vids))
    #logging.debug('known vids processed - '+str(len(user_videos)))    
    vids = instantvidsite.Video.gql("WHERE user = :1 AND status = :2 AND site = :3", user,
                               'rejected', site.key())
    user_videos.extend(browse.ConvertVideosToDisplayObjects(vids))
    #logging.debug('known vids processed - '+str(len(user_videos)))
    #logging.debug(user_videos)
                  
    # do one write back for anything updated, but these may be from different entity groups
    #if len(updated_videos) > 0:
    #  db.put(updated_videos)               
    for update in updated_videos:
      update.put()
    
    browse.PrintHeader(self.request, self.response, site, site.display_name+ ' - my account')
    
    removed_vid = self.request.get('justremoved')
    
    template_values = {'user_videos': user_videos,
                       'updatedvids': updated_videos,
                       'site': site,
                       'justremoved': browse.if_else(removed_vid is None or
                                                       removed_vid == "", None,
                                                       removed_vid)}

    path = os.path.join(os.path.dirname(__file__), 'account.html')
    self.response.out.write(template.render(path, template_values))
 
    
class FavoriteVideo(webapp.RequestHandler):
  
  """request to favorite a given video id."""
  
  @login_required
  def get(self, sitepath):
    
    """get method."""
    
    #find domain
    site = instantvidsite.GetSite(sitepath)
    if not site:
      logging.error('bad sitepath - '+str(sitepath))
      self.redirect("/?error=siteunknown")
      return
            
    #make sure id field is present
    id = self.request.get('id')
    if id is None or id == '':
      self.redirect('/a/'+site.path)  #throw a bad url error here
      return
      
    #retrieve TubeUser, create if none
    t_user = browse.GetTubeUser(site)
    if t_user is None:  #create account if none when accessing account page
      t_user = instantvidsite.TubeUser()
      t_user.user = users.GetCurrentUser()
      t_user.site = site.key()
      
    #set featured video
    t_user.featured_video = id
    t_user.put()
    
    self.redirect('/a/'+site.path+'/PlayVideo?id=' + id + ';justfeatured=1', True)
    
class FeatureVideo(webapp.RequestHandler):
  
  """request to favorite a given video id."""
  
  @login_required
  def get(self, sitepath):
    
    """get method."""
    
    #find domain
    site = instantvidsite.GetSite(sitepath)
    if not site:
      self.redirect("/?error=siteunknown")
      return
            
    #make sure id field is present
    id = self.request.get('id')
    if id is None or id == '':
      self.redirect('/a/'+site.path)  #throw a bad url error here
      return
      
    if users.GetCurrentUser() != site.owner:      
      self.redirect("/?error=notsiteowner")
      return
      
    #set featured video
    site.featured_video = id
    site.put()
    
    self.redirect('/a/'+site.path+'/PlayVideo?id=' + id + ';justfeatured=1', True)

    
class RemoveVideo(webapp.RequestHandler):
  
  """request to remove a video id you own (doesn't remove from youtube)."""
  
  @login_required
  def get(self, sitepath):
    
    """get method."""
    
    #find domain
    site = instantvidsite.GetSite(sitepath)
    if not site:
      logging.error('bad sitepath - '+str(sitepath))
      self.redirect("/?error=siteunknown")
      return
      
    #make sure id field is present
    id = self.request.get('id')
    if id is None or id == '':
      self.redirect('/a/'+site.path)
      #TODO(gabe): throw a bad url error here
      return
      
    #retrieve TubeUser, create if none
    t_user = browse.GetTubeUser(site)
    if t_user is None:  #create account if none when accessing account page
      t_user = instantvidsite.TubeUser()
      t_user.user = users.GetCurrentUser()
      t_user.site = site.key()
      
    #remove video
    for video in instantvidsite.Video.gql("WHERE user = :1 AND id = :2 AND site = :3",
                                     t_user.user, id, site.key()):
      video.delete()
    
    self.redirect('/a/'+site.path+'/acct?justremoved=' + id)
    

class ClearAuthToken(webapp.RequestHandler):
  
  """request to remove your authsub token if it's not working"""
  
  @login_required
  def get(self, sitepath):
    
    """get method."""
    
    #find domain
    site = instantvidsite.GetSite(sitepath)
    if not site:
      logging.error('bad sitepath - '+str(sitepath))
      self.redirect("/?error=siteunknown")
      return
          
    #retrieve TubeUser, create if none
    browse.ClearAuthSubToken()
    
    self.redirect('/a/'+site.path+'/acct?justclearedtoken')
      
                        
def main():
  application = webapp.WSGIApplication([(r'/a/([^/]*)/acct', Account),
                                        (r'/a/([^/]*)/acct/FavoriteVideo', FavoriteVideo),
                                        (r'/a/([^/]*)/acct/FeatureVideo', FeatureVideo),
                                        (r'/a/([^/]*)/acct/ClearYTToken', ClearAuthToken),
                                        (r'/a/([^/]*)/acct/RemoveVideo', RemoveVideo)],
                                        debug=False)

  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
